import { EventEmitter } from '../utils';
import { NetworkError } from '../errors';

/**
 * 连接类
 */
export default class Connection {
  constructor() {
    this.emitter = new EventEmitter();
  }

  async connect(url) {
    if (!url) console.warn('ws url not valid: ', url);
    this.url = url;
    await new Promise((resolve, reject) => {
      this.connection = new WebSocket(this.url);
      /**
       * 监听消息响应
       * @param e
       */
      this.connection.onmessage = (e) => {
        this.$emit('message', e.data);
      };
      /**
       * 监听连接关闭
       * @param e
       */
      this.connection.onclose = (e) => {
        this.$emit('close', e);
      };
      /**
       * 监听底层错误
       * @param e
       */
      this.connection.onerror = (e) => {
        this.$emit('error', e);
      };

      /**
       * 监听底层建立
       * @param e
       */
      this.connection.onopen = (e) => {
        this.$emit('open', e);
      };

      this.connection.addEventListener('error', reject);
      this.connection.addEventListener('open', resolve);

      // eslint-disable-next-line no-promise-executor-return
      return this.connection;
    });
  }

  send(data) {
    this.connection.send(data);
  }

  close() {
    this.connection.close();
  }

  onMessage(fn, once) {
    this.$on('message', fn, null, once);
  }

  offMessage(fn) {
    this.$off('message', fn);
  }

  onClose(fn) {
    this.$on('close', fn);
  }

  onOpen(fn) {
    this.$on('open', fn);
  }

  onError(fn) {
    this.$on('error', fn);
  }

  $on(names, fn, handle = null, once = false) {
    this.emitter.on(names, fn, handle, once);
  }

  $emit(name, ...args) {
    this.emitter.emit(name, ...args);
  }

  $off(name, cb, handle) {
    this.emitter.remove(name, cb, handle);
  }
}
